#include "protocol_07645.h"



//struct FuncCodeAnaly func_code_analy[func_code_count]
//{
//    {0x00, "保留"},
//    {RADIATE_TIMING, "广播校时"},
//    {READ_DATA, "读数据"},
//    {READ_FOLLOWING_DATA, "读后续数据"},
//    {READ_METER_ADDR, "读通信地址"},
//    {WRITE_DATA, "写数据"},
//    {WRITE_METER_ADDR, "写通信地址"},
//    {RADIATE_FREEZE, "冻结命令"},
//    {SET_COMM_VELOCITY, "改通信速率"},
//    {SET_PASSWORD, "修改密码"},
//    {METER_CLEAR, "电表清零"},
//    {EVENT_CLEAR, "事件清零"}
//};


struct frame07645 *get_645_frame(uint8_t *in, int len)
{
    int i = 0, dlen;
    struct frame07645 *pframe;

start_check:
    while (i < len)
    {
        if ( (0x68 == in[i] )
         &&  (0x68 == in[i+7]))
            break;
        i++;
    }

    if (len - i < FRAME_645_SZ)
        return NULL;

    pframe = (struct frame07645 *) (in + i);
    dlen = pframe->data_len;

    if (i + FRAME_645_SZ + dlen > len)
        return NULL;

    if (0x68 != pframe->st2)
    {
        i++;
        goto start_check;
    }

    if (pframe->data[dlen] != checksum((uint8_t *)(in + i), dlen + FRAME_645_HEAD))
        return NULL;

    if (pframe->data[dlen + 1] != 0x16)
        return NULL;

    memadd(pframe->data, -0x33, pframe->data_len);

    return pframe;
}


/*
功能：根据645的DID，解析出DID对应的文字说明
参数：DID字符串，如"00010000"，解析结果输出在字符串AnalyStr中，形如
*/
void get_645_did_analysis(QString did_str, QString &DidAnalyStr)
{
    QString filter_tmp = model_645_did->filter();
    model_645_did->setFilter("");

    int row=0;
    for(row=0;row<model_645_did->rowCount();row++ )
    {
        QString dbDId_str = model_645_did->record(row).value("DID").toString();
        if(dbDId_str == did_str)
        {
            break;
        }
    }
    if(row >= model_645_did->rowCount())
    {
        DidAnalyStr += "无法解析该did";
    }
    else
    {
        DidAnalyStr += model_645_did->record(row).value("instruction").toString();//只筛选出一条信息的话，筛选结果位于record(0)中
    }

    model_645_did->setFilter(filter_tmp);


//    model_645_did->setFilter(QString("did LIKE '%%1%' ").arg(did_str));
//    model_645_did->select();
//    if(model_645_did->rowCount()<1)//未找到
//    {
//        DidAnalyStr += "无法解析该did";
//    }
//    else
//    {
//        DidAnalyStr += model_645_did->record(0).value("instruction").toString();//只筛选出一条信息的话，筛选结果位于record(0)中
//    }
//    model_645_did->setFilter("");
}
/*
功能：根据645的DID，解析出DID对应的body域的真实值
参数：DID字符串，如"02010100"读电压，要解析的字符串body_frame_str如"22 05",解析结果为"220.5V"输出到BodyAnalyStr
*/
void get_645_body_analysis(QString did_str, QString body_frame_str,QString &BodyAnalyStr)
{
    body_frame_str = body_frame_str.replace(QString(" "),QString(""));//删除空格

    int row=0;
    for(row=0;row<model_645_did->rowCount();row++ )
    {
        QString dbDId_str = model_645_did->record(row).value("DID").toString();
        if(dbDId_str == did_str)
        {
            break;
        }
    }
    if(row == model_645_did->rowCount())
    {
        return;
    }
    QString dbAnalysisCode_str = model_645_did->record(row).value("analysisCode").toString();
    QStringList SL = dbAnalysisCode_str.split('+');
    bool isOK;
    qDebug("分析码用+切割，共%d段", SL.count());
    for(int str_idx = 0;str_idx<SL.count();str_idx++)
    {
        qDebug()<<"第"<<str_idx<<"段:"<<SL.at(str_idx);
        QString analy_num_str = SL.at(str_idx);
        analy_num_str.toFloat(&isOK);
        if(isOK)//确实是数字
        {
            int int_part_len = analy_num_str.left(1).toInt();//整数部分长度
            int dec_part_len = analy_num_str.right(1).toInt();//小数部分长度
            qDebug()<<"整数长:"<<int_part_len<<" 小数长"<<dec_part_len;

            BodyAnalyStr += QString::number(body_frame_str.left(int_part_len).toInt());
            body_frame_str.remove(0,int_part_len);
            if(dec_part_len != 0 )
            {
                BodyAnalyStr += "." + body_frame_str.left(dec_part_len);
            }

        }
        else
        {
            BodyAnalyStr += SL.at(str_idx);
        }


    }


}
/*
功能：解析07645报文
参数：07645报文首地址pframe(数据域已减掉33H)，解析结果字符串AnalyStr
*/
void analysis_07645_frame(struct frame07645 *pframe, QString &AnalyStr)
{
    AnalyStr += "<p>07645解析：<gy></gy></p>" ;
    //quint32 meter_addr_num= *(quint32 *)pframe->meter_addr;
    quint32 meter_addr_num = get_le_val(pframe->meter_addr, 4);
    AnalyStr += "<p>电表地址:<gy>" + QString::number(meter_addr_num,16).toUpper()+"(bcd格式)</gy></p>";
    uint8 control_byte = pframe->control_byte;
    AnalyStr += "<p>控制字:<gy>0x" + QString("%1").arg(control_byte,2,16,(QChar)'0').toUpper()+"</gy></p>";

    //控制字详细解析，方向、异常、功能码

    if(0 == pframe->direction_flag)
        AnalyStr += "<p> 方向:<gy>主->从</gy></p>";
    else
    {
        AnalyStr += "<p> 方向:<gy>从->主</gy></p>";
        if(pframe->exception_flag)
        {
            AnalyStr += QString("<p> 应答:<gy>异常,代码(hex)为: 0x%1</gy></p>").arg(pframe->data[0],2,16,(QChar)'0');
            return;
        }
        else
        {
             AnalyStr += "<p> 应答:<gy>正常</gy></p>";
        }
    }

    //
    bool isOK;
    int db_row=0;//先定位到db中某功能码所在的行
    for(db_row=0;db_row < model_645_FuncCode->rowCount();db_row++)
    {
        QString dbFuncCode_str = model_645_FuncCode->record(db_row).value("funcCode").toString().left(2);
        uint8 dbFuncCode = dbFuncCode_str.toInt(&isOK,16);
        if( pframe->function_flag ==  dbFuncCode)
        {
            AnalyStr += QString("<p> 功能码:<gy>0x%1 ->").arg(pframe->function_flag,2,16,(QChar)'0')
                    +model_645_FuncCode->record(db_row).value("instruction").toString() + "</gy></p>";
            break;
        }
    }
    if(db_row == model_645_FuncCode->rowCount() )
    {
        AnalyStr += "目前不支持该功能码，在功能码维护界面添加后即可支持</gy></p>";
        return ;
    }

    int data_len = pframe->data_len;
    AnalyStr += "<p>数据域长度:<gy>" + QString("%1").arg(pframe->data_len) +"</gy></p>";
    if(data_len == 0)
        return;
    AnalyStr += "<p>数据域HEX原文(-33H后):<gy>";
    QString  DataAnalyStr_tmp;
    DataAnalyStr_tmp = byte_num_to_hex_string_with_space(pframe->data, pframe->data_len);
    AnalyStr += DataAnalyStr_tmp + "</gy></p>";

    //下面解析数据域pframe->data，控制码不同，则解析方式不同

    AnalyStr += "<p>数据域解析:<gy></gy></p>";//DID PW OP BODY


    //解析did(如果该功能码有did的话)
    int data_len_tmp= 0;
    QString containDid_str = model_645_FuncCode->record(db_row).value("ContainDid").toString();
    if(containDid_str == "是")
    {
        data_len_tmp += 4;
        QString did_str = QString("%1").arg(get_le_val(pframe->data, 4), 8,16,(QChar)'0').toUpper();
        AnalyStr += "<p>DID:<gy>0x" + did_str + "-->";
        QString did_instruction_str;
        get_645_did_analysis(did_str,did_instruction_str);
        AnalyStr += did_instruction_str + "</gy></p>";
    }

    QString containPW_OP_str = model_645_FuncCode->record(db_row).value("ContainPW_OP").toString();
    if(containPW_OP_str == "是")
    {
        data_len_tmp += 8;
        struct _data_645write *data_645write = (struct _data_645write *)(pframe->data);
        AnalyStr += QString("<p>密码:<gy>0x%1</gy></p>").arg(get_le_val(data_645write->password, 4), 8,16,(QChar)'0').toUpper();
        AnalyStr += QString("<p>操作者代码:<gy>0x%1</gy></p>").arg(get_le_val(data_645write->manipulator, 4), 8,16,(QChar)'0').toUpper()+"\r\n";
    }

    QString containBody = model_645_FuncCode->record(db_row).value("containBody").toString();
    if((containBody == "是") || (pframe->data_len - data_len_tmp>0) )
    {
        QString writeDataAnalyStr = byte_num_to_hex_string_with_space(pframe->data + data_len_tmp, pframe->data_len - data_len_tmp,true);
        AnalyStr += "<p>数据(按报文顺序):<gy> " + writeDataAnalyStr +"</gy></p>";
        writeDataAnalyStr = byte_num_to_hex_string_with_space(pframe->data + data_len_tmp, pframe->data_len - data_len_tmp,false);
        AnalyStr += "<p>数据(反报文顺序):<gy> " + writeDataAnalyStr + "</gy></p>";
        if(containDid_str == "是")
        {
            QString did_str = QString("%1").arg(get_le_val(pframe->data, 4), 8,16,(QChar)'0').toUpper();
            QString body_analysis_str;
            get_645_body_analysis(did_str, writeDataAnalyStr, body_analysis_str);
            AnalyStr += "<p>body解析:<gy> " + body_analysis_str + "</gy></p>";
        }

    }


}
